﻿using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.Windows.Forms;
using MyWcfLib;

namespace MyWcfMon
{
    internal class MyWcfServiceProxy
    {
        string m_server;
        string m_domain;
        string m_userName;
        string m_password;
        int m_port;

        internal MyWcfServiceProxy(string server, int port, string userName, string password, string domain)
        {
            m_server = server;
            m_port = port;
            m_userName = userName;
            m_password = password;
            m_domain = domain;
        }

        internal MyWcfServiceResponse ExecuteCommand(MyWcfServiceCommand command)
        {
            var tcpBinding = new NetTcpBinding(SecurityMode.None, false)
                                 {
                                     ReceiveTimeout = new TimeSpan(0, 30, 0),
                                     SendTimeout = new TimeSpan(0, 30, 0),
                                     CloseTimeout = new TimeSpan(0, 1, 30),
                                     MaxBufferPoolSize = 1048576,
                                     MaxConnections = 10,
                                     MaxReceivedMessageSize = 4194304,
                                     OpenTimeout = new TimeSpan(0, 1, 30)
                                 };
            tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
            tcpBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;

            var sb = new ServiceBehaviorAttribute {IncludeExceptionDetailInFaults = true};


            var endpointAddress = new EndpointAddress(string.Format("net.tcp://{0}:{1}/MyWcfServiceControl", m_server, m_port));
            var proxy = new MyWcfServiceControlClient(tcpBinding, endpointAddress);

            //Note: current user credentials are used unless we use runtime provided credentials like this 
            //NetworkCredential credentials = new NetworkCredential(m_userName, m_password);
            //if (m_domain != null) credentials = new NetworkCredential(m_userName, m_password, m_domain);
            //proxy.ClientCredentials.Windows.ClientCredential = credentials;

            var response = proxy.ExecuteCommand(command);


            //if proxy is in Faulted state, Close throws CommunicationObjectFaultedException
            if (proxy.State != CommunicationState.Faulted) proxy.Close();

            return response;
        }
        internal MyWcfServiceResponse ExecuteRead(MyWcfServiceCommand command)
        {
            var tcpBinding = new NetTcpBinding(SecurityMode.None, false)
                                 {
                                     ReceiveTimeout = new TimeSpan(0, 30, 0),
                                     SendTimeout = new TimeSpan(0, 30, 0),
                                     CloseTimeout = new TimeSpan(0, 1, 30),
                                     MaxBufferPoolSize = 1048576,
                                     MaxConnections = 10,
                                     MaxReceivedMessageSize = 4194304,
                                     OpenTimeout = new TimeSpan(0, 1, 30)
                                 };
            tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
            tcpBinding.Security.Transport.ProtectionLevel = ProtectionLevel.EncryptAndSign;

            var sb = new ServiceBehaviorAttribute {IncludeExceptionDetailInFaults = true};


            var endpointAddress = new EndpointAddress(string.Format("net.tcp://{0}:{1}/MyWcfServiceControl", m_server, m_port));
            var proxy = new MyWcfServiceControlClient(tcpBinding, endpointAddress);

            //Note: current user credentials are used unless we use runtime provided credentials like this 
            //NetworkCredential credentials = new NetworkCredential(m_userName, m_password);
            //if (m_domain != null) credentials = new NetworkCredential(m_userName, m_password, m_domain);
            //proxy.ClientCredentials.Windows.ClientCredential = credentials;

            var response = proxy.ExecuteRead(command);


            //if proxy is in Faulted state, Close throws CommunicationObjectFaultedException
            if (proxy.State != CommunicationState.Faulted) proxy.Close();

            return response;
        }
        class MyWcfServiceControlClient : ClientBase<IMyWcfServiceControl>, IMyWcfServiceControl
        {
            public MyWcfServiceControlClient(System.ServiceModel.Channels.Binding binding, EndpointAddress address) : base(binding, address) { }
            public MyWcfServiceResponse ExecuteCommand(MyWcfServiceCommand command)
            {
                MyWcfServiceResponse response = null;
                try
                {
                    response = Channel.ExecuteCommand(command);
                }
                catch (SecurityNegotiationException ne)
                {
                    response = new MyWcfServiceResponse() { Response = ne.Message };
                }
                catch (SecurityAccessDeniedException ae)
                {
                    response = new MyWcfServiceResponse() { Response = ae.Message };
                }
                return response;
            }
            public MyWcfServiceResponse ExecuteRead(MyWcfServiceCommand command)
            {
                MyWcfServiceResponse response = null;
                try
                {
                    response = Channel.ExecuteRead(command);
                }
                catch (SecurityNegotiationException ne)
                {
                    response = new MyWcfServiceResponse() { Response = ne.Message };
                }
                catch (SecurityAccessDeniedException ae)
                {
                    response = new MyWcfServiceResponse() { Response = ae.Message };
                }
                return response;
            }
        }
    }
}
